home *** CD-ROM | disk | FTP | other *** search
- {===EZDSLDBL==========================================================
-
- Part of the Delphi Structures Library--the double linked list.
-
- EZDSLDBL is Copyright (c) 1993, 1996 by Julian M. Bucknall
-
- VERSION HISTORY
- 13Mar96 JMB 2.00 release for Delphi 2.0
- 12Nov95 JMB 1.01 fixed Iterate bug
- 18Jun95 JMB 1.00 conversion of EZStrucs to Delphi
- ======================================================================}
- { Copyright (c) 1993, 1996, Julian M. Bucknall. All Rights Reserved }
-
- unit EZDSLDbl;
-
- {$I EZDSLDEF.INC}
- {---Place any compiler options you require here-----------------------}
-
-
- {---------------------------------------------------------------------}
- {$I EZDSLOPT.INC}
-
- interface
-
- uses
- SysUtils,
- WinTypes,
- WinProcs,
- Classes,
- EZDSLCts,
- EZDSLSup,
- EZDSLBse;
-
- type
-
- TDList = class(TAbstractContainer)
- {-Double linked list object}
- private
- FIsSorted: boolean;
- BF, AL : PNode;
-
- public
- constructor Create(DataOwner : boolean); override;
- constructor Clone(Source : TAbstractContainer;
- DataOwner : boolean; NewCompare : TCompareFunc); override;
-
- function Delete(Cursor : TListCursor) : TListCursor;
- procedure Empty; override;
- function Erase(Cursor : TListCursor) : TListCursor;
- function Examine(Cursor : TListCursor) : pointer;
- procedure InsertAfter(Cursor : TListCursor; aData : pointer);
- procedure InsertBefore(Cursor : TListCursor; aData : pointer);
- procedure InsertSorted(aData : pointer);
- function IsAfterLast(Cursor : TListCursor) : boolean;
- function IsBeforeFirst(Cursor : TListCursor) : boolean;
- function Iterate(Action : TIterator; Backwards : boolean;
- ExtraData : pointer) : pointer;
- procedure Join(Cursor : TListCursor; List : TDList);
- function Next(Cursor : TListCursor) : TListCursor;
- function Prev(Cursor : TListCursor) : TListCursor;
- function Replace(Cursor : TListCursor; aData : pointer) : pointer;
- function Search(var Cursor : TListCursor; aData : pointer) : boolean;
- function SetBeforeFirst : TListCursor;
- function SetAfterLast : TListCursor;
- function Split(Cursor : TListCursor) : TDList;
-
- {properties}
- property IsSorted: boolean
- read FIsSorted;
- end;
-
- implementation
-
- {-An iterator for cloning a double linked list}
- function DListClone(SL : TAbstractContainer;
- aData : pointer;
- NSL : pointer) : boolean; far;
- var
- NewList : TDList absolute NSL;
- NewData : pointer;
- begin
- Result := true;
- with NewList do
- begin
- if IsDataOwner then
- NewData := DupData(aData)
- else NewData := aData;
- try
- InsertBefore(SetAfterLast, NewData);
- except
- DisposeData(NewData);
- raise;
- end;
- end;
- end;
-
- {-An iterator for cloning a SORTED double linked list}
- function DListSortedClone(SL : TAbstractContainer;
- aData : pointer;
- NSL : pointer) : boolean; far;
- var
- NewList : TDList absolute NSL;
- NewData : pointer;
- begin
- Result := true;
- with NewList do
- begin
- if IsDataOwner then
- NewData := DupData(aData)
- else NewData := aData;
- try
- InsertSorted(NewData);
- except
- DisposeData(NewData);
- raise;
- end;
- end;
- end;
-
- {=TDList==============================================================}
- constructor TDList.Create(DataOwner : boolean);
- begin
- NodeSize := 12;
- inherited Create(DataOwner);
- BF := acNewNode(nil);
- FCount := 0;
- AL := acNewNode(nil);
- FCount := 0;
- BF^.FLink := AL;
- BF^.BLink:= BF;
- AL^.FLink := AL;
- AL^.BLink:= BF;
- FIsSorted := true;
- end;
- {--------}
- constructor TDList.Clone(Source : TAbstractContainer;
- DataOwner : boolean;
- NewCompare : TCompareFunc);
- var
- OldList : TDList absolute Source;
- begin
- Create(DataOwner);
- Compare := NewCompare;
- DupData := OldList.DupData;
- DisposeData := OldList.DisposeData;
-
- if not (Source is TDList) then
- RaiseError(escBadSource);
-
- if OldList.IsEmpty then Exit;
-
- if OldList.IsSorted then
- OldList.Iterate(DListSortedClone, false, Self)
- else OldList.Iterate(DListClone, false, Self);
- end;
- {--------}
- function TDList.Delete(Cursor : TListCursor) : TListCursor;
- var
- Temp : PNode;
- begin
- {$IFDEF DEBUG}
- Assert((not IsBeforeFirst(Cursor)) and (not IsAfterLast(Cursor)), ascDeleteEdges);
- {$ENDIF}
- Temp := PNode(Cursor);
- Cursor := Next(Cursor);
- Temp^.BLink^.FLink := PNode(Cursor);
- PNode(Cursor)^.BLink := Temp^.BLink;
- acDisposeNode(Temp);
- Delete := Cursor;
- if IsEmpty then
- FIsSorted := true;
- end;
- {--------}
- procedure TDList.Empty;
- var
- Cursor : TListCursor;
- begin
- if not IsEmpty then
- begin
- Cursor := Next(SetBeforeFirst);
- while not IsAfterLast(Cursor) do
- Cursor := Erase(Cursor);
- end;
- if InDone then
- begin
- if Assigned(BF) then
- acDisposeNode(BF);
- if Assigned(AL) then
- acDisposeNode(AL);
- end;
- end;
- {--------}
- function TDList.Erase(Cursor : TListCursor) : TListCursor;
- begin
- if IsDataOwner then
- DisposeData(Examine(Cursor));
- Erase := Delete(Cursor);
- end;
- {--------}
- function TDList.Examine(Cursor : TListCursor) : pointer;
- begin
- {$IFDEF DEBUG}
- Assert((not IsBeforeFirst(Cursor)) and (not IsAfterLast(Cursor)), ascExamineEdges);
- {$ENDIF}
- Examine := PNode(Cursor)^.Data;
- end;
- {--------}
- procedure TDList.InsertAfter(Cursor : TListCursor; aData : pointer);
- var
- Node : PNode;
- begin
- {$IFDEF DEBUG}
- Assert(not IsAfterLast(Cursor), ascInsertEdges);
- {$ENDIF}
- Node := acNewNode(aData);
- Node^.FLink := PNode(Cursor)^.FLink;
- Node^.BLink:= PNode(Cursor);
- PNode(Cursor)^.FLink := Node;
- Node^.FLink^.BLink := Node;
- FIsSorted := false;
- end;
- {--------}
- procedure TDList.InsertBefore(Cursor : TListCursor; aData : pointer);
- var
- Node : PNode;
- begin
- {$IFDEF DEBUG}
- Assert(not IsBeforeFirst(Cursor), ascInsertEdges);
- {$ENDIF}
- Node := acNewNode(aData);
- Node^.FLink := PNode(Cursor);
- Node^.BLink:= PNode(Cursor)^.BLink;
- PNode(Cursor)^.BLink := Node;
- Node^.BLink^.FLink := Node;
- FIsSorted := false;
- end;
- {--------}
- procedure TDList.InsertSorted(aData : pointer);
- var
- Walker : TListCursor;
- begin
- if not IsSorted then
- begin
- Walker := SetAfterLast;
- InsertBefore(Walker, aData);
- end
- else {the list is sorted}
- begin
- if Search(Walker, aData) then
- RaiseError(escInsertDup)
- else
- begin
- InsertBefore(Walker, aData);
- FIsSorted := true;
- end;
- end;
- end;
- {--------}
- function TDList.IsAfterLast(Cursor : TListCursor) : boolean;
- begin
- IsAfterLast := (PNode(Cursor) = AL);
- end;
- {--------}
- function TDList.IsBeforeFirst(Cursor : TListCursor) : boolean;
- begin
- IsBeforeFirst := (PNode(Cursor) = BF);
- end;
- {--------}
- function TDList.Iterate(Action : TIterator; Backwards : boolean;
- ExtraData : pointer) : pointer;
- var
- Walker : TListCursor;
- begin
- if Backwards then
- begin
- Walker := Prev(SetAfterLast);
- while not IsBeforeFirst(Walker) do
- if Action(Self, Examine(Walker), ExtraData) then {!!.01}
- Walker := Prev(Walker)
- else
- begin
- Result := Examine(Walker);
- Exit;
- end;
- end
- else
- begin
- Walker := Next(SetBeforeFirst);
- while not IsAfterLast(Walker) do
- if Action(Self, Examine(Walker), ExtraData) then {!!.01}
- Walker := Next(Walker)
- else
- begin
- Result := Examine(Walker);
- Exit;
- end;
- end;
- Result := nil; {!!.01}
- end;
- {--------}
- procedure TDList.Join(Cursor : TListCursor; List : TDList);
- var
- Walker : TListCursor;
- Data : pointer;
- begin
- {$IFDEF DEBUG}
- Assert(not IsAfterLast(Cursor), ascCannotJoinHere);
- Assert(List.IsDataOwner = IsDataOwner, ascCannotJoinData);
- {$ENDIF}
- if not Assigned(List) then Exit;
-
- if not List.IsEmpty then
- begin
- {if we are sorted, add new nodes in sorted order}
- if {Self.}IsSorted then
- begin
- Walker := List.Next(List.SetBeforeFirst);
- while not List.IsAfterLast(Walker) do
- begin
- Data := List.Examine(Walker);
- Walker := List.Delete(Walker);
- InsertSorted(Data);
- end;
- end
- else
- begin
- List.AL^.BLink^.FLink := PNode(Cursor)^.FLink;
- PNode(Cursor)^.FLink^.BLink := List.AL^.BLink;
- PNode(Cursor)^.FLink := List.BF^.FLink;
- PNode(Cursor)^.FLink^.BLink := PNode(Cursor);
- inc(FCount, List.Count);
- {patch up List to be empty}
- with List do
- begin
- BF^.FLink := AL;
- AL^.BLink := BF;
- FCount := 0;
- end;
- end;
- end;
- List.Free;
- end;
- {--------}
- function TDList.Next(Cursor : TListCursor) : TListCursor;
- begin
- {$IFDEF DEBUG}
- Assert(not IsAfterLast(Cursor), ascAlreadyAtEnd);
- {$ENDIF}
- Next := TListCursor(PNode(Cursor)^.FLink);
- end;
- {--------}
- function TDList.Prev(Cursor : TListCursor) : TListCursor;
- begin
- {$IFDEF DEBUG}
- Assert(not IsBeforeFirst(Cursor), ascAlreadyAtStart);
- {$ENDIF}
- Prev := TListCursor(PNode(Cursor)^.BLink);
- end;
- {--------}
- function TDList.Replace(Cursor : TListCursor; aData : pointer) : pointer;
- begin
- {$IFDEF DEBUG}
- Assert((not IsBeforeFirst(Cursor)) and (not IsAfterLast(Cursor)), ascReplaceEdges);
- {$ENDIF}
- if IsSorted then
- begin
- Replace := Examine(Cursor);
- Delete(Cursor);
- InsertSorted(aData);
- end
- else
- with PNode(Cursor)^ do
- begin
- Replace := Data;
- Data := aData;
- end;
- end;
- {--------}
- function TDList.Search(var Cursor : TListCursor; aData : pointer) : boolean;
- var
- Walker : TListCursor;
- CompResult : integer;
- StillLooking : boolean;
- Found : boolean;
- begin
- Walker := SetBeforeFirst;
- if IsSorted then
- begin
- CompResult := 1;
- while (CompResult > 0) do
- begin
- Walker := Next(Walker);
- if IsAfterLast(Walker) then
- CompResult := -1
- else CompResult := Compare(aData, Examine(Walker));
- end;
- Cursor := Walker;
- Search := (CompResult = 0);
- end
- else {the list is not sorted}
- begin
- StillLooking := true;
- Found := false;
- while StillLooking and (not Found) do
- begin
- Walker := Next(Walker);
- if IsAfterLast(Walker) then
- StillLooking := false
- else Found := (Compare(aData, Examine(Walker)) = 0);
- end;
- Cursor := Walker;
- Search := Found;
- end;
- end;
- {--------}
- function TDList.SetBeforeFirst : TListCursor;
- begin
- SetBeforeFirst := TListCursor(BF);
- end;
- {--------}
- function TDList.SetAfterLast : TListCursor;
- begin
- SetAfterLast := TListCursor(AL);
- end;
- {--------}
- function TDList.Split(Cursor : TListCursor) : TDList;
- var
- TempCount : longint;
- NewList : TDList;
- Walker : TListCursor;
- LastNodeLeftBehind,
- JoinNode,
- LastNode : PNode;
- begin
- {$IFDEF DEBUG}
- Assert((not IsBeforeFirst(Cursor)) and (not IsAfterLast(Cursor)), ascSplitEdges);
- {$ENDIF}
- NewList := TDList(TAbstractContainerClass(ClassType).Create(IsDataOwner));
- NewList.Compare := Compare;
- NewList.DupData := DupData;
- NewList.DisposeData := DisposeData;
- Result := NewList;
-
- LastNodeLeftBehind := PNode(Cursor)^.BLink;
-
- TempCount := 0;
- Walker := Cursor;
- JoinNode := PNode(Walker);
- while not IsAfterLast(Walker) do
- begin
- inc(TempCount);
- Walker := Next(Walker);
- end;
-
- LastNode := PNode(Prev(Walker));
-
- JoinNode^.BLink := NewList.BF;
- NewList.BF^.FLink := JoinNode;
- LastNode^.FLink := NewList.AL;
- NewList.AL^.BLink := LastNode;
- NewList.FCount := TempCount;
- NewList.FIsSorted := IsSorted;
-
- dec(FCount, TempCount);
- LastNodeLeftBehind^.FLink := AL;
- AL^.BLink := LastNodeLeftBehind;
- if IsEmpty then
- FIsSorted := true;
- end;
- {---------------------------------------------------------------------}
-
- end.
-